module aru_psb_rdgen_addr_calc (
    input logic                             clk,
    input logic                             rst_n,
          aru_idx_if.in                     u_aru_idx_if,
          aru_psb_rdgen_cfg_if.addr_calc_in u_aru_cfg_if,
          aru_sdb_if.in                     u_aru_sdb_from_crd_gen_if,
          aru_sdb_if.out                    u_aru_sdb_to_sdb_fifo_if,
          psb_rd_req_if.out                 u_psb_rd_req_if
);

    logic cfg_vld;
    logic lst_req_in_instr;
    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            cfg_vld <= 'd0;
        end else if (cfg_vld) begin
            if (u_psb_rd_req_if.vld && u_psb_rd_req_if.rdy && lst_req_in_instr) begin
                cfg_vld <= 'd0;
            end
        end else begin
            if (u_aru_cfg_if.vld) begin
                cfg_vld <= 1'b1;
            end
        end
    end
    assign u_aru_cfg_if.rdy = !cfg_vld;
    assign lst_req_in_instr = u_aru_sdb_from_crd_gen_if.pld.eom && u_aru_sdb_from_crd_gen_if.pld.eon;

    idx_t slice_m1 = (u_aru_cfg_if.slice_m + `M0 - 1) / `M0;
    idx_t slice_n1 = (u_aru_cfg_if.slice_n + `N0 - 1) / `N0;

    // PSB address calculation
    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            u_psb_rd_req_if.psb_addr <= 'd0;
        end else begin
            // PSB中按照m1n1m0n0的顺序存储数据
            u_psb_rd_req_if.psb_addr <= u_aru_cfg_if.psb_addr
                                    + (u_aru_idx_if.pld.m1_idx * slice_n1 * `M0 + (u_aru_idx_if.pld.n1_idx * `M0 + u_aru_idx_if.pld.p_idx * `P_ARU)) * `N0 * 2;


        end
    end

    logic has_data;
    logic up_vld, up_rdy, down_vld, down_rdy;
    assign down_rdy = u_psb_rd_req_if.rdy && u_aru_sdb_to_sdb_fifo_if.rdy;
    assign up_vld   = u_aru_sdb_from_crd_gen_if.vld && u_aru_cfg_if.vld && u_aru_idx_if.vld;
    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            has_data <= 'd0;
        end else if (has_data) begin
            if (~up_vld && down_rdy) begin
                has_data <= 'd0;
            end
        end else begin
            if (up_vld) begin
                has_data <= 'd1;
            end
        end
    end
    assign down_vld                      = has_data;
    assign up_rdy                        = (~has_data) || down_rdy;

    assign u_aru_sdb_to_sdb_fifo_if.vld  = cfg_vld && down_vld;
    assign u_aru_sdb_to_sdb_fifo_if.pld  = u_aru_sdb_from_crd_gen_if.pld;


    assign u_psb_rd_req_if.vld           = cfg_vld && down_vld;
    assign u_aru_sdb_from_crd_gen_if.rdy = up_rdy && cfg_vld;

endmodule
